<!-- ChatMessages.vue -->
<template>
  <t-list ref="chatBox" class="message-list">
    <!-- 消息区域 -->
    <div class="message-container">
      <div
        v-for="msg in messages"
        :key="msg.id"
        class="message-item"
        :class="{ user: msg.type === 'user', assistant: msg.type === 'answer' }"
      >
        <div v-if="msg.type === 'user'" class="user-message">
          <div class="content">{{ msg.content }}</div>
          <div class="content">{{ msg.files }}</div>
        </div>

        <div v-if="msg.type === 'assistant'" class="answer-message">
          <!--  assistant 头部区域    -->
          <div class="answer-header" style="margin-bottom: 20px">
            <t-avatar
              image="https://tdesign.gtimg.com/site/avatar.jpg"
              class="avatar"
              style="margin-right: 15px; border: 1px solid var(--td-brand-color-active)"
            />
            <span class="avatar-sub" style="color: var(--td-text-color-placeholder)">{{
              dayjs(msg.timestamp).format('MM-DD HH:mm:ss')
            }}</span>
          </div>
          <!--  assistant 思考内容    -->
          <t-collapse
            v-if="msg.thinkingContent || msg.isThinkingLoading"
            class="avatar-think"
            expand-icon-placement="right"
            :default-expand-all="msg.showThinking"
            style="border-radius: 12px; margin-bottom: 20px"
          >
            <t-collapse-panel :header="123">
              <!-- 加载状态 -->
              <div v-if="msg.isThinkingLoading" class="think-loading">
                <!--                <t-spinner size="small" />-->
                <span>深度思考中...</span>
              </div>

              <!-- 实际内容 -->
              <pre v-else style="white-space: pre-wrap">
                {{ msg.thinkingContent }}
              </pre>
            </t-collapse-panel>
          </t-collapse>
          <!--  assistant 回答正文    -->
          <div class="content">
            <!-- 加载状态 -->
            <t-loading v-if="msg.isLoading" :loading="msg.isLoading" />
            <div v-else-if="!msg.isLoading && msg.contentType === 'card'" class="card-content">
              <json-viewer v-if="isValidJSON(msg.content)" :value="JSON.parse(msg.content)" />
              <div v-else class="invalid-card">无效的卡片数据</div>
            </div>
            <template v-else-if="!msg.isLoading && msg.type === 'file'">
              <div class="file-message">
                <t-icon name="file" />
                <span>{{ msg.content }}</span>
                <t-button @click="$emit('preview-file', msg)">预览</t-button>
              </div>
            </template>
            <template v-else>
              <div class="markdown-content" v-html="renderMarkdown(msg.content)" />
            </template>
          </div>
        </div>
        <!-- 知识库引用       -->
        <!-- 推荐追问问题       -->
        <div v-if="msg.type === 'follow_up'" class="suggestions">
          <t-button v-for="(suggestion, idx) in msg.suggestions" :key="idx" variant="outline" size="small">
            {{ suggestion }}
          </t-button>
        </div>
      </div>
    </div>
  </t-list>
</template>

<script setup lang="ts">
import { defineProps, defineEmits, watch, nextTick, onMounted, ref } from 'vue';
import JsonViewer from 'vue3-json-viewer';
import VMdPreview from '@kangc/v-md-editor/lib/preview';
import '@kangc/v-md-editor/lib/style/preview.css';
import githubTheme from '@kangc/v-md-editor/lib/theme/github.js';

import MarkdownIt from 'markdown-it';
import markdownItMultimdTable from 'markdown-it-multimd-table';
import markdownItCodeCopy from 'markdown-it-code-copy';
import hljs from 'highlight.js';
import DOMPurify from 'dompurify';
import dayjs from 'dayjs';

defineProps({
  messages: { type: Array, required: true },
  isLoading: { type: Boolean, required: true },
});

VMdPreview.use(githubTheme, {
  Hljs: hljs,
});

const chatBox = ref(null); // 获取滚动容器引用

// 初始化 markdown-it 实例
const md = new MarkdownIt({
  html: true, // 允许HTML标签
  linkify: true, // 自动转换URL为链接
  typographer: true, // 优化排版
  tables: true, // 启用表格解析
  // xhtmlOut: false, // 关闭XHTML格式输出
  // breaks: false, // 关闭自动换行转换
  highlight: (str, lang) => {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return `<pre class="hljs"><code>${
          hljs.highlight(str, {
            language: lang,
            ignoreIllegals: true,
          }).value
        }</code></pre>`;
      } catch (__) {}
    }
    return `<pre class="hljs"><code>${md.utils.escapeHtml(str)}</code></pre>`;
  },
});

// 添加表格插件（支持复杂表格）
md.use(markdownItMultimdTable, {
  multiline: true,
  rowspan: true,
  headerless: true,
});

// eslint-disable-next-line func-names,
md.renderer.rules.table_open = function (tokens, idx, options, env, self) {
  return '<div class="table-wrapper"><table>';
};

// eslint-disable-next-line func-names
md.renderer.rules.table_close = function (tokens, idx, options, env, self) {
  return '</table></div>';
};

// Markdown 渲染方法
const renderMarkdown = (content: string) => {
  // 剥离代码块标记
  const cleanContent = content;
  // 清除起始标记（支持多种格式）
  // .replace(/^```\s*html?\s*\n?/gim, '') // 匹配 html/HTML/Html
  // // 清除结束标记
  // .replace(/\n?```\s*$/gim, '')
  // // 清除游离标记
  // .replace(/(^|\n)```(\n|$)/g, '\n');

  // 空内容处理
  if (!cleanContent.trim()) return '';
  // 执行Markdown解析
  const htmlOutput = md.render(cleanContent);
  // return htmlOutput;

  // 安全过滤
  return DOMPurify.sanitize(htmlOutput, {
    ALLOWED_TAGS: [
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6',
      'ul',
      'ol',
      'li',
      'p',
      'div',
      'br',
      'strong',
      'em',
      'a',
      'img',
      'code',
      'pre',
      'span',
      'blockquote',
      'table',
      'thead',
      'tbody',
      'tr',
      'th',
      'td',
    ],
    ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'class', 'width', 'height'],
  });
};

defineEmits(['suggestion-click', 'preview-file']);

const isValidJSON = (str) => {
  try {
    JSON.parse(str);
    return true;
  } catch {
    return false;
  }
};
</script>

<style lang="less">
// 添加Markdown内容样式
.markdown-content {
  line-height: 1.6;
  // 标题样式
  h1,
  h2,
  h3 {
    font-size: 18px;
    font-weight: 600;
  }
  h4,
  h5,
  h6 {
    font-size: 16px;
    font-weight: 600;
  }

  // 代码块样式
  pre.hljs {
    padding: 1em;
    border-radius: 12px;
    background: var(--td-bg-color-container);
    margin: 1em 0;
    overflow-x: auto;
    border: 1px solid var(--td-component-stroke);
    box-shadow: var(--td-shadow-1), inset 0 1px 0 0 rgba(255, 255, 255, 0.1); // 内嵌光泽效果

    code {
      counter-reset: line; // 行号计数器
      font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
    }
    // 行号装饰
    code > .line {
      &::before {
        counter-increment: line;
        content: counter(line);
        display: inline-block;
        width: 2.5em;
        margin-right: 1.5em;
        color: var(--td-text-color-placeholder);
        text-align: right;
        user-select: none;
      }
    }

    // 右上角语言标签
    &::after {
      content: attr(data-language);
      position: absolute;
      top: 0;
      right: 0;
      padding: 0.3em 1.2em;
      background: var(--td-brand-color);
      color: var(--td-text-color-anti);
      font-size: 0.8em;
      font-weight: 500;
      border-radius: 0 12px 0 12px;
      text-transform: uppercase;
      letter-spacing: 0.05em;
    }

    .hljs {
      &-keyword {
        color: #ff7f50;
        font-weight: 600;
      } // 橙色
      &-string {
        color: #98c379;
      } // 绿色
      &-comment {
        color: #728096;
        font-style: italic;
      } // 灰色斜体
      &-title {
        color: #e06c75;
      } // 红色
      &-meta {
        color: #56b6c2;
      } // 青色
    }
  }

  /* 表格包装器样式 */
  .table-wrapper {
    border: 1px solid var(--td-border-level-1-color); /* 边框 */
    border-radius: 12px; /* 圆角 */
    overflow-x: auto; /* 横向滚动 */
    max-width: 100%; /* 限制宽度 */
    margin-bottom: 15px;
    /* 表格样式 */
    table {
      border-collapse: collapse; /* 合并边框 */
      width: 100%; /* 表格宽度自适应 */
    }
    th,
    td {
      width: auto;
      padding: 0.6em 1em;
      min-width: 100px; /* 最小列宽 */
      border: 1px solid var(--td-component-border);
      background-color: var(--td-bg-color-container);
    }

    th {
      background-color: var(--td-brand-color);
      color: var(--td-text-color-anti);
      font-weight: 600;
    }
    /* 特定列定制（如日期列） */
    td:nth-child(1) {
      width: 120px; /* 固定日期列宽度 */
    }
  }

  // 其他元素样式
  ul {
    font-size: 16px;
    list-style-type: disc;
    padding-left: 2em;
    //margin: 1em 0;

    li {
      list-style-type: inherit;
      &::marker {
        color: var(--td-text-color-placeholder);
      }
    }
  }

  ol {
    font-size: 16px;
    list-style-type: decimal;
    padding-left: 2em;
    //margin: 1em 0;

    li {
      list-style-type: inherit;
      &::marker {
        color: var(--td-text-color-placeholder);
      }
    }
  }
  // 段落样式
  p {
    font-size: 16px;
    //color: #333;
  }

  blockquote {
    color: var(--td-text-color-placeholder);
    border-left: 4px solid #dfe2e5;
    padding-left: 1em;
    //margin: 1em 0;
  }

  a {
    color: var(--td-text-color-link);
    text-decoration: none;

    &:hover {
      text-decoration: underline;
    }
  }
}
</style>

<style lang="less" scoped>
@import url('../index.less');
:deep(.t-collapse-panel__content) {
  padding: var(--td-comp-paddingTB-m) var(--td-comp-paddingTB-m);
}
:deep(.t-collapse-panel__wrapper .t-collapse-panel__header) {
  border-radius: 12px;
}
:deep(.t-collapse-panel__wrapper .t-collapse-panel__body) {
  border-radius: 0 0 12px 12px;
}
</style>
